package cn.sangyy.auth.service.impl;

import cn.sangyy.auth.annotation.Permission;
import cn.sangyy.auth.domain.Permiss;
import cn.sangyy.auth.mapper.PermissMapper;
import cn.sangyy.auth.service.IPermissionScanService;
import cn.sangyy.basic.common.RequestTypeEnum;
import cn.sangyy.basic.utils.ClassUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;

/**
 * @author SangYY
 * @date: 2023/05/16/20:27
 */
@Service
public class PermissionScanServiceImpl implements IPermissionScanService {

    @Value("${permission.scan-base-package}")
    private String scanBasePackage;

    @Autowired
    private PermissMapper permissMapper;

    /**
    * @author Sangyy
    * 权限扫描
    */
    @Override
    @Transactional
    public void scan() {
        //拿到所有controller下类的字节码
        List<Class> allClass = ClassUtils.getAllClassName(scanBasePackage);
        //因为每次扫描就会添加到数据库，所以扫描前删除所有的权限数据
        permissMapper.deleteAll();
        for (Class aClass : allClass) {
            Permission annotation = (Permission)aClass.getAnnotation(Permission.class);
            if(Objects.isNull(annotation)){
                continue;
            }
            //获取类上的url
            RequestMapping requestMapping = (RequestMapping)aClass.getAnnotation(RequestMapping.class);
            String classUrl = requestMapping.value()[0];
            //类上的注解也要解析为一个permission对象
            Permiss classPer = new Permiss();
            classPer.setName(annotation.name());
            classPer.setDesc(annotation.desc());
            classPer.setUrl(classUrl);
            classPer.setSn(aClass.getSimpleName());
            permissMapper.insert(classPer);
            //类上有权限注解，拿到那些方法有权限注解
            Method[] methods = aClass.getMethods();
            for (Method method : methods) {
                Permission methodAnnotation = method.getAnnotation(Permission.class);
                if(Objects.isNull(methodAnnotation)){
                    continue;
                }
                //如果方法上有注解，封装成一个permission对象
                Permiss permiss = new Permiss();
                permiss.setDesc(methodAnnotation.desc());
                permiss.setName(methodAnnotation.name());
                String methodUrl = getMethodUrl(method);
                permiss.setUrl(classUrl+methodUrl);
                //sn唯一标识
                permiss.setSn(aClass.getSimpleName()+":"+method.getName());
                permiss.setParentId(classPer.getId());
                permissMapper.insert(permiss);
            }
        }
    }

    private String getMethodUrl(Method method){
        String methodUrl = "";
        // 取枚举中定义的所有的请求类型
        RequestTypeEnum[] requestTypeEnums = RequestTypeEnum.values();
        for (RequestTypeEnum typeEnum : requestTypeEnums) {
            // 根据枚举中的不同的请求类型的class获取该类型对应的注解对象
            Annotation annotation = method.getAnnotation(typeEnum.getRequestType());
            // 如果该请求类型注解不存在就跳过
            if(Objects.isNull(annotation)){
                continue;
            }
            try {
                // 如果该请求类型注解存在,就获取它里面的value方法
                Method annotationMethod = annotation.annotationType().getMethod("value");
                // 通过invoke调用该对象的value方法,获取结果
                String[] value = (String[]) annotationMethod.invoke(annotation);
                // 如果value不为空且长度大于0,就赋值给methodUrl,并跳出循环
                if(value != null && value.length > 0){
                    methodUrl = value[0];
                    break;
                }
            }catch (Exception e) {
                e.printStackTrace();
                continue;
            }
        }
        return methodUrl;
        /*PutMapping putMapping = method.getAnnotation(PutMapping.class);
        if(Objects.nonNull(putMapping)){
            methodUrl = putMapping.value() != null && putMapping.value().length > 0 ? putMapping.value()[0] : "";
        }
        PostMapping postMapping = method.getAnnotation(PostMapping.class);
        if(Objects.nonNull(postMapping)){
            methodUrl = postMapping.value() != null && postMapping.value().length > 0 ? postMapping.value()[0] : "";
        }
        GetMapping getMapping = method.getAnnotation(GetMapping.class);
        if(Objects.nonNull(getMapping)){
            methodUrl = getMapping.value() != null && getMapping.value().length > 0? getMapping.value()[0] : "";
        }
        DeleteMapping deleteMapping = method.getAnnotation(DeleteMapping.class);
        if(Objects.nonNull(deleteMapping)){
            methodUrl = deleteMapping.value() != null && deleteMapping.value().length > 0 ? deleteMapping.value()[0] : "";
        }
        PatchMapping patchMapping = method.getAnnotation(PatchMapping.class);
        if(Objects.nonNull(patchMapping)){
            methodUrl = patchMapping.value() != null && patchMapping.value().length > 0 ? patchMapping.value()[0] : "";
        }*/
        //return methodUrl;
    }
}
